//
// Created by Martin on 2022/10/3.
//
#include <iostream>
using namespace std;

template<typename T>
struct type_descriptor
{
    static std::string value;
    operator const char* ()
    {
        return value.c_str();
    }

    std::string& operator()()
    {
        return value;
    }
};

// static 成员初始化在类外

template<typename T>
std::string type_descriptor<T>::value = "unknown type";

template<>
std::string type_descriptor<char>::value = "char";

template<>
std::string type_descriptor<short>::value = "short";

template<>
std::string type_descriptor<int>::value = "int";

template<>
std::string type_descriptor<long>::value = "long";

template<>
std::string type_descriptor<float>::value = "float";

template<>
std::string type_descriptor<double>::value = "double";

// 偏特化T const
template<typename T>
struct type_descriptor<T const>
{
    operator const char* ()
    {
        static std::string value = static_cast<const char *>(type_descriptor<T>());
        value += " const";
        return value.c_str();
    }

    std::string& operator()()
    {
        static std::string value = type_descriptor<T>();
        value += " const";
        return value;
    }
};

// 偏特化T*
template<typename T>
struct type_descriptor<T*>
{
    operator const char* ()
    {
        static std::string value = static_cast<const char *>(type_descriptor<T>());
        value += " *";
        return value.c_str();
    }

    std::string& operator()()
    {
        static std::string value = type_descriptor<T>();
        value += " const";
        return value;
    }
};

// 偏特化T&
template<typename T>
struct type_descriptor<T&>
{
    operator const char* ()
    {
        static std::string value = static_cast<const char *>(type_descriptor<T>());
        value += " &";
        return value.c_str();
    }

    std::string& operator()()
    {
        static std::string value = type_descriptor<T>();
        value += " const";
        return value;
    }
};

static void test_type_descriptor()
{
    std::cout << type_descriptor<int>() << std::endl;           // int
    std::cout << type_descriptor<char*>() << std::endl;         // char *
    std::cout << type_descriptor<long const*&>() << std::endl;  // long const * &
}

int main()
{
    test_type_descriptor();
    return 0;
}